
-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "air780e-mqttdemo"
VERSION = "1.0.0"

--[[
本demo需要mqtt库, 大部分能联网的设备都具有这个库
mqtt也是内置库, 无需require
]]

-- sys库是标配
_G.sys = require("sys")
--[[特别注意, 使用mqtt库需要下列语句]]
_G.sysplus = require("sysplus")

--根据自己的服务器修改以下参数
local mqtt_host = "iot.isuoge.com"
local mqtt_port = 1883
local mqtt_isssl = false
local client_id = mcu.unique_id()
local user_name = "air780e"
local password = "air780e"
local maxbatv = 3300
local mqttc = nil

-- 网络状态
local netStatus = false

-- gpio定义
local netLedPin = 27 --网络灯
local pinData = {
    fishLight = {
        pin = 1,--定义引脚
        actionTime = 0, --触发的时间，用来记录上次启动时间 方便计算运行时长
        cdTime = 0, -- 关闭触发间隔时间(单位:秒)，防止设备长时间运行
        value = 0, -- 引脚电平
        pinType = "gpio" -- 引脚触发类型  gpio 0 1  pwm 0-100
    },
    balconyWater = {
        pin = 8,
        actionTime = 0,
        cdTime = 300,
        value = 0,
        pinType = "gpio"
    },
    fishFilter = {
        pin = 10,
        actionTime = 0,
        cdTime = 0,
        value = 0,
        pinType = "gpio"
    },
    fishFeed = {
        pin = 9,
        actionTime = 0,
        cdTime = 2,
        value = 0,
        pinType = "gpio"
    },


}


-- 网络灯闪烁
function netLedShine()
    local isLight = false
    while true do
        if isLight then
            gpio.set(netLedPin,0)
        else
            gpio.set(netLedPin,1)
        end
        isLight = not isLight
        if netStatus then
            sys.wait(3000)
        else
            sys.wait(500)
        end
        log.info("网络状态",netStatus)
    end
end

--IO操作
function ioHandle(pinName,value)
    for key, item in pairs(pinData) do
        if key == pinName then
            gpio.set(pinData[pinName].pin,value)
            pinData[pinName].value = value
            print('pinName',pinName,pinData[pinName].value)
        end
    end
end

-- gpio引脚初始化
gpio.setup(netLedPin, 0)
gpio.setup(pinData.fishLight.pin,0, gpio.PULLDOWN,gpio.BOTH)
gpio.setup(pinData.balconyWater.pin,0, gpio.PULLDOWN,gpio.BOTH)
gpio.setup(pinData.fishFilter.pin,0, gpio.PULLDOWN,gpio.BOTH)
gpio.setup(pinData.fishFeed.pin,0, gpio.PULLDOWN,gpio.BOTH)




sys.taskInit(function()
    -----------------------------
    -- 统一联网函数, 可自行删减
    ----------------------------
    -- Air780E/Air600E系列
    --mobile.simid(2)

    device_id = mobile.imei()
    sys.waitUntil("IP_READY", 30000)
    netStatus = true
    log.info('网络连接成功')
    sys.subscribe("IP_READY", function(adapter)
        netStatus = true
        log.info("网络连接", "IP_READY")
    end)
    sys.subscribe("IP_LOSE", function(adapter)
        netStatus = false
        log.info("网络丢失", "IP_LOSE")
    end)


    -- 打印一下支持的加密套件, 通常来说, 固件已包含常见的99%的加密套件
    if crypto.cipher_suites then
        log.info("cipher", "suites", json.encode(crypto.cipher_suites()))
    end


    socket.sntp()--同步时间
    local luatos_version = rtos.version()
    log.info("luatos_version",luatos_version)
    -------------------------------------
    -------- MQTT 演示代码 --------------
    -------------------------------------

    mqttc = mqtt.create(nil,mqtt_host, mqtt_port, mqtt_isssl, ca_file)

    mqttc:auth(device_id,user_name,password) -- client_id必填,其余选填
    mqttc:keepalive(30) -- 默认值240s
    mqttc:autoreconn(true, 3000) -- 自动重连机制

    mqttc:on(function(mqtt_client, event, data, payload)
        -- 用户自定义代码
        log.info("mqtt", "event", event, mqtt_client, data, payload)
        if event == "conack" then
            sys.publish("mqtt_conack")
            mqtt_client:subscribe("/iot/smartgarden/air780e/io_controller")
        elseif event == "recv" then
            log.info("mqtt", "downlink", "topic", data, "payload", payload,os.time(),os.date)
            local t = rtc.get()
            log.info("rtc", json.encode(t))
            -- gpio.set(22, 1)--引脚高电平
            local payloadData =  json.decode(payload)
            if payloadData.type == "ioHandle" then
                --IO操作
                ioHandle(payloadData.data.name,payloadData.data.value)
                if  payloadData.data.value>0 then--记录开始时间
                    pinData[payloadData.data.name].actionTime = os.time()
                end

            end
        elseif event == "sent" then
            log.info("mqtt", "sent", "pkgid", data)
        -- elseif event == "disconnect" then
            -- 非自动重连时,按需重启mqttc
            -- mqtt_client:connect()
        end
    end)

    mqttc:connect()
	sys.waitUntil("mqtt_conack")
    while true do
        -- mqttc自动处理重连
        local ret, topic, data, qos = sys.waitUntil("mqtt_pub", 30000)
        if ret then
            if topic == "close" then break end
            mqttc:publish(topic, data, qos)
        end
    end
    mqttc:close()
    mqttc = nil
end)

local function GetPreciseDecimal(nNum, n)
    if type(nNum) ~= "number" then
        return nNum;
    end
    n = n or 0;
    n = math.floor(n)
    if n < 0 then
        n = 0;
    end
    local nDecimal = 10 ^ n
    local nTemp = math.floor(nNum * nDecimal);
    local nRet = nTemp / nDecimal;
    return nRet;
end




--添加硬狗防止程序卡死
if wdt then
    wdt.init(9000)--初始化watchdog设置为9s
    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
end

--网络状态灯，单独开协程处理是避免sys.wait()对其他逻辑的阻塞
sys.taskInit(function ()
    netLedShine()
end)

--处理io状态和传感器数据
sys.taskInit(function()
	local topic = "/iot/smartgarden/air780e/io_status"
    while true do
        -- 5秒发送一次数据
        sys.wait(3000)
        if mqttc and mqttc:ready() then

            local tmp,hum -- 原始数据
            local temp,humi -- 真实值

            --1010 000x
            local addr = 0x40
            -- 按实际修改哦
            local id = 0

            log.info("i2c", "initial",i2c.setup(0))


            --第一种方式
            i2c.send(id, addr, string.char(0xF3))
            sys.wait(100)
            tmp = i2c.recv(id, addr, 2)
            log.info("SHT20", "read tem data", tmp:toHex())

            i2c.send(id, addr, string.char(0xF5))
            sys.wait(100)
            hum = i2c.recv(id, addr, 2)
            log.info("SHT20", "read hum data", hum:toHex())
            local _,tval = pack.unpack(tmp,'>H')
            local _,hval = pack.unpack(hum,'>H')
            if tval and hval then
                temp = ((1750*(tval)/65535-450))/10
                humi = ((1000*(hval)/65535))/10
                log.info("SHT20", "temp,humi",temp,humi)
                log.info("SHT20", "temp,humi",tval,hval)
            end
			-- mqttc:subscribe(topic)
            shidu = 0.00
            if adc.open(0) then
                log.info("adc-get",adc.get(0))
                maxv,adcv =  3300,adc.get(0)
                if adcv>maxv then
                    adcv = maxv
                end
                shidu = GetPreciseDecimal((maxv - adcv)/maxv*100,2)
            else
                log.info("adc-open faile")
            end


            --读取引脚数据
            local data = {
                soilhumi=shidu,
                temp=temp,
                humi=humi
            }
            for key, item in pairs(pinData) do
                data[key] = pinData[key].value
            end

            jsondata = json.encode({type="ioStatus",data=data})
            local pkgid = mqttc:publish(topic, jsondata, qos)
            -- 也可以通过sys.publish发布到指定task去
            -- sys.publish("mqtt_pub", topic, data, qos)
        end
    end
end)

-- 处理IO超时
sys.taskInit(function ()
    while true do
        sys.wait(500)
        --工作超时保护，防止设备运行超时（比如浇水水泵）  配置cdTime大于0时生效 为0则可以不间断运行（比如过滤泵）
        for key, item in pairs(pinData) do
            if pinData[key].cdTime >0 and pinData[key].value>0 and  os.time() - pinData[key].actionTime > pinData[key].cdTime then
                ioHandle(key,0)
                print('触发超时保护',key,pinData[key].value)
            end
        end
    end
end)
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
